﻿using System;
using System.Collections;
using System.Collections.Generic;
using Common.Data.Scriptable;
using Cysharp.Threading.Tasks;
using DG.Tweening;
using UnityEngine;
using WssEvents;
using WssUtils;

/*
 * 合成管理器，用来管理合成逻辑的判断
 */
namespace JQMergeFramework
{
    /// <summary>
    /// 枚举，用来检测元素之间合成的状态
    /// </summary>
    public enum MergeState
    {
        Merge,
        Exchage,
        Place,
        Origin,
    }
    public class MergeManager : Singleton<MergeManager>
    {
        //行
        public int row = 5;
        //列
        public int col = 5;
        
        
        /// <summary>
        /// 地形格子
        /// </summary>
        public GroundBase[,] groundArray;
        
        
        /// <summary>
        /// 逻辑处理用，记录遍历格子
        /// </summary>
        private List<GroundBase> mRecodGround = new List<GroundBase>();

        

        //游戏预制体信息
        public ScriptableObjectPrefab scriptablePrefab;
        
        //上一局的游戏层数
        public int lastLayerNum = 0;

        //是否在使用消除道具
        public bool isUseRemoveProp = false;

        //是否在使用移动道具
        public bool isUseMoveProp = false;
        
       
        //是否游戏结束
        public bool isGameOver = false;
        
        //记录移动房子信息
        private Queue<CityUnit> moveRecordCityQu = new Queue<CityUnit>();

        private NumericalCfg _numericalCfg;
        public NumericalCfg NumericalCfg
        {
            get
            {
                return _numericalCfg;
            }
        }



        #region 开始游戏逻辑(棋盘内随机生成3个建筑)


        private bool isInit = false;
        public void Init()
        {
            if (!isInit)
            {
                //初始化数据
                DataManager.Instance.Init();
                TableConfig.Instance.Init();
                isInit = true;
            }
            
            _numericalCfg = TableConfig.Instance.GetNumericalCfg(DataManager.Instance.Lv+1);
            scriptablePrefab = Resources.Load<ScriptableObjectPrefab>("ScriptableObjectPrefab");

            MergeManager.Instance.isGameOver = false;
        }

        /// <summary>
        /// 开始游戏时放置3个城堡
        /// </summary>
        public void StartPlaceThree()
        {
            TowerControl.I.InitPlaceThreeCity().Forget();
        }

        #endregion


        #region 游戏事件
        //是否在使用随机事件
        public bool isUseEventUI = false;
        private float gameTime = 0;
        private EventTypes lastEvent = EventTypes.Node;
        
        public void Update()
        {
            if (!isUseEventUI && !isGameOver)
            {
                gameTime += Time.deltaTime;
                
                if (gameTime >= GameCfg.EventShowTime && !InputManager.I.isNoRayClick)
                {
                    if (lastEvent == EventTypes.Node)
                    {
                        lastEvent = MyRandom.Bool() ? EventTypes.UAV:EventTypes.Helicopter;
                        //优先无人机
                        if (DataManager.Instance.DayLimitUAV > 0 && DataManager.Instance.DayLimitCopter > 0)
                        {
                      
                        }
                        else
                        {
                            if (DataManager.Instance.DayLimitUAV > 0)
                            {
                                lastEvent = EventTypes.UAV;
                            }
                            else
                            {
                                lastEvent = EventTypes.Helicopter;
                            }
                        }
                    }
                    else
                    {
                        lastEvent = lastEvent == EventTypes.UAV ? EventTypes.Helicopter : EventTypes.UAV;
                    }

                    if (lastEvent == EventTypes.UAV)
                    {
                        if (DataManager.Instance.DayLimitUAV > 0)
                        {
                            GlobalEvent.Dispatcher(GameEvents.OnShowEvent,lastEvent);  
                        }
                        else if(DataManager.Instance.DayLimitCopter > 0)
                        {
                            GlobalEvent.Dispatcher(GameEvents.OnShowEvent,lastEvent);  
                        }
                    }
                    else if (lastEvent == EventTypes.Helicopter)
                    {
                        if (DataManager.Instance.DayLimitCopter > 0)
                        {
                            GlobalEvent.Dispatcher(GameEvents.OnShowEvent,lastEvent);  
                        }
                        else if(DataManager.Instance.DayLimitUAV > 0)
                        {
                            GlobalEvent.Dispatcher(GameEvents.OnShowEvent,lastEvent);  
                        }
                    }
                    
                    gameTime = MyRandom.Range(0,120);
                }
            }
        }
        
        #endregion
        
        #region 六边形合成逻辑


        private List<CityUnit> GetSameList(CityUnit lastPlace)
        {
            mRecodGround.Clear();
            
            List<CityUnit> sameCity = new List<CityUnit>();
            GroundBase ground = lastPlace.mGroundBase;
            
            if (ground!=null)
            {
                sameCity.Add(lastPlace);

                int lastRow = ground.row;
                int lastCol = ground.col;

                GroundBase[,] groundAry = groundArray;
                for (int i = 0; i < 6; i++)
                {
                    Vector2Int ncpos = CommonFun.GetNear(lastRow, lastCol, (HexGrid.Dir)i);
                
                    if (CommonFun.IsInRange(ncpos.x, ncpos.y) && !groundAry[ncpos.x,ncpos.y].IsDisabled)
                    {
                        DetectionGround(groundAry[ncpos.x,ncpos.y],lastPlace.Level,ref sameCity);
                    }
                }
            }

            return sameCity;
        }

        /// <summary>
        /// 刷新棋盘，判断是否有符合合成的格子
        /// </summary>
        /// <param name="lastPlace">最近放下的城堡信息</param>
        public void RefreshGround(CityUnit lastPlace)
        {
            List<CityUnit> sameCity = GetSameList(lastPlace);
            // Debug.Log("可合成数量："+sameCity.Count +"----LEVLE:"+lastPlace.unitData.UnitLevel);
            
            //可以合成。升级、再遍历一遍是否可以合成
            if (sameCity.Count >= GameCfg.LimitMargeNum)
            {
               DelayMarge(lastPlace, sameCity).Forget();
            }
            else
            {
                
                //执行一下。是否存在可以合成的
                if (moveRecordCityQu.Count > 0)
                {
                    RefreshGround(moveRecordCityQu.Dequeue());
                }
                else
                {
                    //通关判断
                    if (this.IsGamePass())
                    {
                        GamePass();
                        return;
                    }
                    else
                    {
                        if (IsGameFail())
                        {
                            if (DataManager.Instance.DayLimitHelicopter > 0)
                            {
                                //没有可放置的位置
                                UIManager.Instance.GetWindow<UIOver>().Open();
                            }
                            else
                            {
                                TowerControl.I.ShowPlaceTipsEft(false);
                                //失败动画
                                MergeManager.Instance.ClearRecord();
                            }
                        }
                    }
                }
            }
        }

        //是否在盖房子
        public bool isPlayNewMainCity = false;
        
        public void GamePass()
        {
            isPlayNewMainCity = true;
            
            DataManager.Instance.Lv++;
            //更新配置
            _numericalCfg = TableConfig.Instance.GetNumericalCfg(DataManager.Instance.Lv+1);
            
            
            //先提前保存需要盖楼的id
            List<int> idList =  MainCityControl.I.SaveAddBuildId();
            bool isNewAchievement = MainCityControl.I.IsNewAchievementFinish();

            if (isNewAchievement)
            {
                CoroutineQueue.Instance.Push((check) =>
                {
                    UIManager.Instance.GetWindow<UIAchievementFinishTips>().Open(check);
                });
            }
 
            
            TowerControl.I.ShowPlaceTipsEft(false);
            //播放通关动画
            TowerControl.I.StartPassAnim(idList);
        }


        private void DetectionGround(GroundBase ground,int level, ref List<CityUnit> sameCity)
        {
            
            int lastRow = ground.row;
            int lastCol = ground.col;
            
            // Debug.Log("进入判断："+ground.name);
            if (!ground.isCanPlace() &&ground.placeCity.Level == level)
            {
                if (!sameCity.Contains(ground.placeCity))
                {
                    sameCity.Add(ground.placeCity);
                }
            }
            else
            {
                return;
            }

            if (mRecodGround.Contains(ground))
            {
                return;
            }
            
            mRecodGround.Add(ground);

            GroundBase[,] groundAry = groundArray;
            
            //判断6个方向是否有相邻同等级的房子
            for (int i = 0; i < 6; i++)
            {
                Vector2Int ncpos = CommonFun.GetNear(lastRow, lastCol, (HexGrid.Dir)i);
                
                if (CommonFun.IsInRange(ncpos.x, ncpos.y) && !groundAry[ncpos.x,ncpos.y].IsDisabled)
                {
                    DetectionGround(groundAry[ncpos.x,ncpos.y],level,ref sameCity);
                }
            }
            
        }
        
        #endregion

        #region 合成表现

        //执行合成判断
        public  async UniTask DelayMarge(CityUnit lastPlace, List<CityUnit> sameCity)
        {
            InputManager.I.isNoRayClick = true;
            
            await UniTask.Delay(TimeSpan.FromSeconds(0.1F));
            
            Vector3 movePos = lastPlace.transform.position;
            
            //上移，然后合成。销毁
            for (int i = 0; i < sameCity.Count; i++)
            {
                if (sameCity[i]!=null)
                {
                    // Debug.Log("----合成坐标:" + sameCity[i].mGroundBase.gameObject.name);
                    int insID = sameCity[i].transform.GetInstanceID();

                    DOTween.Kill(insID);
                    sameCity[i].transform.DOMove(movePos + new Vector3(0, lastPlace.mMeshSize.y, 0), 0.3f)
                        .SetEase(Ease.OutBack);
                }
            }
            
            await UniTask.Delay(TimeSpan.FromSeconds(0.15F));


            int _row = lastPlace.mGroundBase.row;
            int _col = lastPlace.mGroundBase.col;
            // Debug.Log("_row:"+_row+"----_col:"+_col);
            GroundBase placeBase = groundArray[_row,_col];
            
            
            CityUnit creatCity = TowerControl.I.LoadCityObj(lastPlace.Level + 1);

            for (int i = 0; i < sameCity.Count; i++)
            {
                sameCity[i].RDestroy();
            }
            
            placeBase.ChangeBindCity(creatCity);
            placeBase.placeCity.audioCtr.Play(AudioName.MergeCity);
            
            //增加拖尾
            GameObject trailing =  EffectPool.I.GetPoolObject(PoolName.MergeTrailing);
            trailing.transform.position = placeBase.mPos;
            Vector3[] pathAry = UIGame.I.GetScoreFillPos(placeBase.mPos);
            float dTime = CommonFun.GetDistance(pathAry) / 120;
            trailing.transform.DOPath(pathAry,dTime, PathType.CatmullRom);
            EffectPool.I.PutPoolObject(PoolName.MergeTrailing,trailing,dTime+0.1F);
            //等待播放完下落动画
            await UniTask.Delay(TimeSpan.FromSeconds(GameCfg.DownTime));
            creatCity.AddMergeScore();
            
            
            //播放合成新房子动画
            TowerControl.I.PlayNewCityTips(creatCity, () =>
            {
                InputManager.I.isNoRayClick = false;
                //检测一下是否可以合成
                RefreshGround(creatCity);
            });
        }

        #endregion


        #region 通关逻辑处理

        public bool IsGamePass()
        {
            int cScore = DataManager.Instance.CurrentScore;
            //判断是否通关
            return cScore >= NumericalCfg.addScore;
        }
        
        //删除棋盘上的所有建筑
        public void ClearCity()
        {
            GroundBase[,] groundAry = groundArray;
            for (int i = 0; i < groundAry.GetLength(0); i++)
            {
                for (int j = 0; j < groundAry.GetLength(1); j++)
                {
                    if (!groundAry[i,j].isCanPlace())
                    {
                        groundAry[i, j].DestroyCity();
                    }
                }
            }
        }

        #endregion
        

        #region 失败判断

        public bool IsGameFail()
        {

            List<GroundBase> groundAry = GetNoDisabled();
            
         
            for (int i = 0; i < groundAry.Count; i++)
            {
                if (groundAry[i].isCanPlace())
                {
                    return false;
                }
            }
            return true;
        }
        
        
        //清空存储的盖楼进度,清零
        public void ClearRecord()
        {
            MergeManager.Instance.isUseRemoveProp = false;
            MergeManager.Instance.lastLayerNum =  DataManager.Instance.BuildCityIdList.Count;
            
            MergeManager.Instance.isGameOver = true;
            
            //楼层破碎
            GameCameraControl.I.CameraFailAnim();
            
            DataManager.Instance.Lv = 0;
            DataManager.Instance.MergeRecordClear();
        }
        #endregion
        
        
        #region 道具处理

        private GroundBase saveOldBase;
        private GroundBase saveNewBase;

        public GroundBase SaveOldBase
        {
            get { return saveOldBase; }
        }
        
        public void SaveClickMoveCity(GroundBase oldBase,GroundBase newBase = null)
        {

            if (newBase)
            {

                saveNewBase = newBase;
                
                DataManager.Instance.SetPropNum(PropId.MoveProp,-1);
  
                CityUnit oldCityUnit = saveOldBase?.placeCity;
                CityUnit newCityUnit = saveNewBase?.placeCity;
                
          
                newBase.ChangeBindCity(saveOldBase.placeCity,true);
                //判断是否可以合成
                RefreshGround(oldCityUnit);
                
                if (newCityUnit)
                {
                    saveOldBase.ChangeBindCity(newCityUnit,true);
                    moveRecordCityQu.Enqueue(oldCityUnit);
                }
                else
                {
                    saveOldBase.ClareCity();
                }
         
                saveOldBase?.ShowTipsGreen(false);
                saveNewBase?.ShowTipsGreen(false);
                
                
                saveOldBase = null;
                saveNewBase = null;
                UIManager.Instance.GetWindow<UsePropItemMask>(false).Close();
            }
            else
            {
                if (saveOldBase!=null)
                {
                    saveOldBase.ShowTipsGreen(false);
                    saveOldBase.placeCity.MoveDefaultPlacePos();
                }
            
                saveOldBase = oldBase;
                oldBase?.ShowTipsGreen(true);
                oldBase?.placeCity.transform.DOLocalMoveY(10, 0.2F);
            }
        }
        

        //取消更换位置
        public void CancelMoveCity()
        {
            
            CityUnit oldCityUnit = saveOldBase?.placeCity;
            CityUnit newCityUnit = saveNewBase?.placeCity;

            oldCityUnit?.DefaultMeshMat();
            newCityUnit?.DefaultMeshMat();
            
            oldCityUnit?.MoveDefaultPlacePos();
            newCityUnit?.MoveDefaultPlacePos();
            
            saveOldBase?.ShowTipsGreen(false);
            saveNewBase?.ShowTipsGreen(false);
            
            moveRecordCityQu.Clear();
            
            saveOldBase = null;
            saveNewBase = null;
        }

        

        /// <summary>
        /// 移除队列中的第一个建筑
        /// </summary>
        public void DiscardCity()
        {
            if (TowerControl.I.isPlayStartCityAnim)
            {
                //动画在播放中，不处理
                return;
            }
            
            if (DataManager.Instance.GetPropNum(PropId.DiscardProp)>0)
            {
                AudioManager.Instance.Play(AudioName.DiscardProp);
                
                DataManager.Instance.SetPropNum(PropId.DiscardProp,-1);
                CityUnit city = TowerControl.I.DequeueUnitDataBase();
                city.RDestroy();
                city.DestroyTrack();
                GlobalEvent.Dispatcher(GameEvents.OnCreateCity);
            }
            else
            {
                Debug.Log("=========道具不足==========");
            }
        }

        
        /// <summary>
        /// 销毁掉选择的建筑
        /// </summary>
        public void RemoveGroundCity(GroundBase rayGround)
        {
            AudioManager.Instance.Play(AudioName.RemoveProp);
            rayGround.placeCity.ChangeMeshMat();
            rayGround.placeCity.PlayAnimRemoveProp();
            GlobalEvent.Dispatcher(GameEvents.OnPropUseResidueNum);
        }
        
        /// <summary>
        /// 重置建筑
        /// </summary>
        public void ResetCityUnitQueue()
        {
            if (TowerControl.I.isPlayStartCityAnim)
            {
                //动画在播放中，不处理
                return;
            }
                
            DataManager.Instance.SetPropNum(PropId.RefreshProp,-1);
            
            AudioManager.Instance.Play(AudioName.RefreshProp);
            
            //根据棋盘生成，获取剩余的空格子，判断一下上下左右，有相同的可以摆放的生成
            GroundBase[,] groundAry = groundArray;
            
            //可放置的位置
            List<GroundBase> groundList = new List<GroundBase>();
            for (int i = 0; i < groundAry.GetLength(0); i++)
            {
                for (int j = 0; j < groundAry.GetLength(1); j++)
                {
                    if (groundAry[i,j].isCanPlace())
                    {
                        groundList.Add(groundAry[i,j]);
                    }
                }
            }
            
            
            //存储（上下左右）不同等级的格子
            List<int> lvList = new List<int>();

            //空余格子>10 纯随机
            if (groundList.Count > 4)
            {
                TowerControl.I.ResetCityUnitQueue(lvList);
                return;
            }
            
            
            Action<CityUnit> levelCall = (city) =>
            {
                if (!lvList.Contains(city.Level))
                {
                    lvList.Add(city.Level);
                }
            };

            for (int i = 0; i < groundList.Count; i++)
            {
                int lastRow = groundList[i].row;
                int lastCol = groundList[i].col;
                //判断6个方向是否有相邻同等级的房子
                for (int j = 0; j < 6; j++)
                {
                    Vector2Int ncpos = CommonFun.GetNear(lastRow, lastCol, (HexGrid.Dir)j);
                    if (CommonFun.IsInRange(ncpos.x, ncpos.y))
                    {
                        GroundBase groundBase = groundAry[ncpos.x, ncpos.y];
                        if (!groundBase.IsDisabled && !groundBase.isCanPlace())
                        {
                            levelCall(groundAry[ncpos.x,ncpos.y].placeCity);
                        }
                    }
                }
            }

            List<int> mayMergeLvList = new List<int>();
            
            for (int i = 0; i < groundList.Count; i++)
            {
                int lastRow = groundList[i].row;
                int lastCol = groundList[i].col;
                
                for (int j = 0; j < lvList.Count; j++)
                {
                    List<CityUnit> sameCity = new List<CityUnit>();
                    mRecodGround.Clear();
                    
                    for (int g = 0; g < 6; g++)
                    {
                        Vector2Int ncpos = CommonFun.GetNear(lastRow, lastCol, (HexGrid.Dir)g);
                        if (CommonFun.IsInRange(ncpos.x, ncpos.y) && !groundAry[ncpos.x,ncpos.y].IsDisabled)
                        {
                            DetectionMergeCity(groundAry[ncpos.x,ncpos.y],lvList[j],ref sameCity);
                        }
                    }
                    
                    
                    if (sameCity.Count >= 2)
                    {
                        if (!mayMergeLvList.Contains(lvList[j]))
                        {
                            mayMergeLvList.Add(lvList[j]);
                        }
                    }
                }
            }
            
            
            TowerControl.I.ResetCityUnitQueue(mayMergeLvList);
            //可以生成
            Debug.Log("可以生成格子等级："+mayMergeLvList.ToString());
        }
        
        private void DetectionMergeCity(GroundBase ground,int lv, ref List<CityUnit> sameCity)
        {
            GroundBase[,] groundAry = groundArray;
            int lastRow = ground.row;
            int lastCol = ground.col;
            
            if (!ground.isCanPlace() && ground.placeCity.Level == lv)
            {
                if (!sameCity.Contains(ground.placeCity))
                {
                    sameCity.Add(ground.placeCity);
                }
            }
            else
            {
                return;
            }

            if (mRecodGround.Contains(ground))
            {
                return;
            }
            
            mRecodGround.Add(ground);
            
            //判断6个方向是否有相邻同等级的房子
            for (int j = 0; j < 6; j++)
            {
                Vector2Int ncpos = CommonFun.GetNear(lastRow, lastCol, (HexGrid.Dir)j);
                if (CommonFun.IsInRange(ncpos.x, ncpos.y))
                {
                    GroundBase groundBase = groundAry[ncpos.x, ncpos.y];

                    if (!groundBase.IsDisabled && !groundBase.isCanPlace())
                    {
                        DetectionMergeCity(groundBase,lv,ref sameCity); 
                    }
                }
            }
        }

        #endregion


        #region 获取信息

        
        //获取场上所有未禁止使用的格子
        public List<GroundBase> GetNoDisabled()
        {
            List<GroundBase> baseAllList = new List<GroundBase>();
            
            for (int i = 0; i < groundArray.GetLength(0); i++)
            {
                for (int j = 0; j < groundArray.GetLength(1); j++)
                {
                    GroundBase gBase = groundArray[i, j];
                    if (!gBase.IsDisabled)
                    {
                        baseAllList.Add(gBase);
                    }
                }
            }
            
            return baseAllList;
        }
        
        
        
        //获取场上已放置的房子
        public List<CityUnit> GetAllPlaceCity()
        {
            List<CityUnit> cityList = new List<CityUnit>();
            
            List<CityUnit> cityAllList = new List<CityUnit>();
            
            for (int i = 0; i < groundArray.GetLength(0); i++)
            {
                for (int j = 0; j < groundArray.GetLength(1); j++)
                {
                    GroundBase gBase = groundArray[i, j];
                    if (!gBase.isCanPlace())
                    {
                        cityAllList.Add(gBase.placeCity);
                    }
                }
            }
            return cityAllList;
        }
        
        //获取放置的最高等级
        public int GetPlaceCityMaxLv()
        {
            int lv = 0;
            for (int i = 0; i < groundArray.GetLength(0); i++)
            {
                for (int j = 0; j < groundArray.GetLength(1); j++)
                {
                    if (!groundArray[i,j].isCanPlace() && groundArray[i,j].placeCity.Level > lv)
                    {
                        lv = groundArray[i, j].placeCity.Level;
                    }
                }
            }

            return lv;
        }

        //获取场上最低等级的三个方子
        public List<CityUnit> GetLowCity()
        {
            List<CityUnit> cityList = new List<CityUnit>();
            
            List<CityUnit> cityAllList = new List<CityUnit>();
            
            for (int i = 0; i < groundArray.GetLength(0); i++)
            {
                for (int j = 0; j < groundArray.GetLength(1); j++)
                {
                    GroundBase gBase = groundArray[i, j];
                    if (!gBase.isCanPlace())
                    {
                        cityAllList.Add(gBase.placeCity);
                    }
                }
            }
            
            cityAllList.Sort((a,b) =>
            {
                return a.UnitData.UnitLevel.CompareTo(b.UnitData.UnitLevel);
            });
            
            
            for (int i = 0; i < cityAllList.Count; i++)
            {
                if (i < GameCfg.HelicopterRemoveCityNum)
                {
                    cityList.Add(cityAllList[i]);
                }
            }
            
            return cityList;
        }
        #endregion


        //删除场上一半的建筑
        public void DesHalfCity()
        {
            List<CityUnit> cityList = new List<CityUnit>();
            
            List<CityUnit> cityAllList = new List<CityUnit>();
            
            for (int i = 0; i < groundArray.GetLength(0); i++)
            {
                for (int j = 0; j < groundArray.GetLength(1); j++)
                {
                    GroundBase gBase = groundArray[i, j];
                    if (!gBase.isCanPlace())
                    {
                        cityAllList.Add(gBase.placeCity);
                    }
                }
            }
            
            cityAllList.Sort((a,b) =>
            {
                return a.UnitData.UnitLevel.CompareTo(b.UnitData.UnitLevel);
            });

            int count = cityAllList.Count / 2;
            
            for (int i = 0; i < cityAllList.Count; i++)
            {
                if (i < count)
                {
                    cityAllList[i].RDestroy();
                }
            }
        }
        
    }
}
